package plateau;

import InterfaceGraphique.ExplorerOuverture;
import InterfaceGraphique.ExplorerSauvegarde;
import InterfaceGraphique.MainApplication;
import cartes.Carte;
import cartes.Monstre;
import common.Constantes;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import munchkin.ParametresPartie;

public class Partie {

    /*
     * Attributs
     */
    private static Pioche piocheTresor;
    private static Pioche piocheDonjon;
    private static Pioche defausse;
    private static ArrayList<Joueur> listeJoueurs;
    private static ParametresPartie parametres;

    public static void setParametres(ParametresPartie parametres) {
        Partie.parametres = parametres;
    }

    public static ParametresPartie getParametres()
    {
        return parametres;
    }

    public static void ChargerParametresJeu()
    {
        if(parametres != null)
        {
                 piocheTresor = parametres.getTresor();
                 piocheDonjon = parametres.getDonjon();
                 defausse = parametres.getDefausse();
                 listeJoueurs = parametres.getListeJoueurs();

                 //On relance le jeu ou il en etait

                MainApplication.showJeuCharge();
                MainApplication.tourDeJeu(Partie.getListeJoueurs().get(0));
        }
    }

    
    private static ObjectInputStream fluxEntree;
    private static ObjectOutputStream fluxSortie;
    private static ExplorerSauvegarde explorateurSauvegarde;
    private static ExplorerOuverture explorateurOuverture;


    /*
     * Faux constructeur car classe statique (non instanciable)
     */
    public static void create(ArrayList<Joueur> lJ) {
        piocheTresor = new Pioche();
        piocheDonjon = new Pioche();
        defausse = new Pioche();
        listeJoueurs = lJ;
        
        CreateCartesInstance cartes = new CreateCartesInstance();
        for(Carte c : cartes.getListeCartes()) {
            if( c.getCategorie() == Constantes.C_DONJON )
                piocheDonjon.add(c);
            else
                piocheTresor.add(c);
        }
    }

    /*
     * Méthodes
     */

    public static void lancerPartie() {
        for( Joueur j : listeJoueurs) {

            j.upNiveau(0, Boolean.TRUE);

            for( int i = 0 ; i < Constantes.NB_CARTES_START ; ++i ) {
                j.getMain().add(j.piocher(Constantes.C_TRESOR));
                j.getMain().add(j.piocher(Constantes.C_DONJON));
            }
        }     
        
    }

    public static void sauvegarder() {
             
            // On cree l'objet parametres a serialiser
            parametres = new ParametresPartie(piocheTresor, piocheDonjon, defausse, listeJoueurs, MainApplication.getJoueurEnCours());

            //On recupere le chemin specifie par l'utilisateur dans l'explorateur
            explorateurSauvegarde = new ExplorerSauvegarde(parametres);
            explorateurSauvegarde.Initialiser();
            explorateurSauvegarde.OuvrirFenetre(null);
        
    }

    public static void charger() throws IOException {

             explorateurOuverture = new ExplorerOuverture();
             explorateurOuverture.Initialiser();
             explorateurOuverture.OuvrirFenetre(null);
                     
    }

    public static void quitter() {
    }
    
    /*
     * Méthode générique permettant de piocher
     * @param : Catégorie de la pioche (trésor ou donjon)
     * @return : La Carte de la pioche demandée 
     * @author : Arthur
     */
    public static Carte piocher(int categorie) {
        Carte c = null;
        
        try {
            // Piocher dans l'une des catégories
            switch(categorie) {
                case Constantes.C_TRESOR :
                    c = piocheTresor.recuperer();
                    break;
                default:
                    c = piocheDonjon.recuperer();
                    break;
            }
        }
        // Cas de figure où on essaye de piocher dans une pioche vide
        catch( ArrayIndexOutOfBoundsException e) {
            // On vérifie la valeur de la catégorie avant de faire de la merde, puis on redistribue
            if ( categorie == Constantes.C_TRESOR || categorie == Constantes.C_DONJON) {
                redistribuerDefausse();                
            }
        }
        
        return c;
    }
    
    
    /*
     * Redistribue la défausse dans les paquets lorsque l'une des pioches est vide
     * @author : Arthur
     */
    public static void redistribuerDefausse() {
        // On défausse toutes les cartes
        defausse.addAll(piocheTresor.vider());
        defausse.addAll(piocheTresor.vider());
        
        // On mélange la défausse
        defausse.melanger();
        
        // Toutes les cartes sont redistribuées dans la bonne pioche
        // NB : La défausse sera ensuite vide
        while( ! defausse.isEmpty() ) {
            Carte c = defausse.recuperer();
            switch( c.getCategorie() ) {
                case Constantes.C_DONJON :
                    piocheDonjon.add(c);
                    break;
                case Constantes.C_TRESOR :
                    piocheTresor.add(c);
                    break;         
            }
        }
    }

    /*@Override
    protected void finalize() throws Throwable {
        this.finalize();
    }*/


    /*
     * Getters & Setters
     */
    public static Pioche getDefausse() {
        return defausse;
    }

    public static void setDefausse(Pioche defausse) {
        Partie.defausse = defausse;
    }

    public static ArrayList<Joueur> getListeJoueurs() {
        return listeJoueurs;
    }

    public static void setListeJoueurs(ArrayList<Joueur> listeJoueurs) {
        Partie.listeJoueurs = listeJoueurs;
    }

    public static Pioche getPiocheDonjon() {
        return piocheDonjon;
    }

    public static void setPiocheDonjon(Pioche piocheDonjon) {
        Partie.piocheDonjon = piocheDonjon;
    }

    public static Pioche getPiocheTresor() {
        return piocheTresor;
    }

    public static void setPiocheTresor(Pioche piocheTresor) {
        Partie.piocheTresor = piocheTresor;
    }

    static void gagner(Joueur j) {
        System.out.println("Partie gagnée par " + j.getNom());
    }

    public static int getLowestNiveau() {
        int min = 10;
        for( Joueur j : listeJoueurs ) {
            if( j.getNiveau() < min ) min = j.getNiveau();
        }
        return min;
    }
    
    public static int getHighestNiveau() {
        int max = 0;
        for( Joueur j : listeJoueurs ) {
            if( j.getNiveau() > max ) max = j.getNiveau();
        }
        return max;
    }
    
}
